package psd.model.Prolog.Converters;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

import psd.model.Prolog.FactGenerationToolbox;


public class PrologCommon {


	public static String GetClassParentID(ASTNode node) {
		if (node == null)
			return "";
		if (node instanceof TypeDeclaration)
			return ((TypeDeclaration) node).getProperty(
					PrologConstants.PROLOG_ID_PROPERTY).toString();
		else
			return GetClassParentID(node.getParent());
	}

	public static String getEmptyList() {
		return "[]";
	}

	public static ArrayList expandList(Iterator bodyIterator) {
		ArrayList expandedList = new ArrayList();
		while (bodyIterator.hasNext()) {
			ASTNode astNode = (ASTNode) bodyIterator.next();
			List fragments = getFragments(astNode);
			if (fragments != null) {
				for (Iterator fieldIterator = fragments.iterator(); fieldIterator
						.hasNext(); expandedList.add(fieldIterator.next())) {
				}
			} else {
				expandedList.add(astNode);
			}
		}
		return expandedList;
	}

	private static List getFragments(ASTNode astNode) {
		switch (astNode.getNodeType()) {
		case 58: // ':'
			return ((VariableDeclarationExpression) astNode).fragments();

		case 60: // '<'
			return ((VariableDeclarationStatement) astNode).fragments();

		case 23: // '\027'
			return ((FieldDeclaration) astNode).fragments();
		}
		return null;
	}

	public static String quote(String str) {
		return (new StringBuilder("'")).append(str).append("'").toString();
	}

	public static int[] excludeComments(ASTNode node) {
		String sourceString = "";
		Javadoc docnode = null;
		List modList = null;
		if (node instanceof AbstractTypeDeclaration) {
			node = (AbstractTypeDeclaration) node;
			docnode = ((AbstractTypeDeclaration) node).getJavadoc();
			modList = ((AbstractTypeDeclaration) node).modifiers();
		} else if (node instanceof MethodDeclaration) {
			node = (MethodDeclaration) node;
			docnode = ((MethodDeclaration) node).getJavadoc();
			modList = ((MethodDeclaration) node).modifiers();
		} else if (node instanceof FieldDeclaration) {
			node = (FieldDeclaration) node;
			docnode = ((FieldDeclaration) node).getJavadoc();
			modList = ((FieldDeclaration) node).modifiers();
		}
		if ((node instanceof AbstractTypeDeclaration)
				| (node instanceof MethodDeclaration)
				| (node instanceof FieldDeclaration)) {
			if (docnode != null) {
				if (modList.size() != 0) {
					IExtendedModifier firstModType = (IExtendedModifier) modList
							.get(0);
					if (firstModType.isModifier()) {
						Modifier modifier = (Modifier) firstModType;
						String modifierString = modifier.getKeyword()
								.toString();
						int javaDocEnd = docnode.getLength()
								+ docnode.getStartPosition();
						int pureStart = sourceString.indexOf(modifierString,
								javaDocEnd);
						int lengthToRemove = pureStart
								- node.getStartPosition();
						int pureLength = node.getLength() - lengthToRemove;
						return (new int[] { pureStart, pureLength });
					} else {
						return (new int[] { node.getStartPosition(),
								node.getLength() });
					}
				}
				int javaDocEnd = docnode.getLength()
						+ docnode.getStartPosition();
				if (node instanceof AbstractTypeDeclaration) {
					int indexOfClass = sourceString
							.indexOf("class", javaDocEnd);
					int indexOfInterface = sourceString.indexOf("interface",
							javaDocEnd);
					int pureStart;
					if (indexOfClass == -1) {
						pureStart = indexOfInterface;
					} else {
						pureStart = indexOfClass;
					}
					int lengthToRemove = pureStart - node.getStartPosition();
					int pureLength = node.getLength() - lengthToRemove;
					return (new int[] { pureStart, pureLength });
				}
				if (node instanceof FieldDeclaration) {
					try {
						List fragList = ((FieldDeclaration) node).fragments();
						String returnType = ((VariableDeclarationFragment) fragList
								.get(0)).resolveBinding().getType().getName();
						int indexOfType = sourceString.indexOf(returnType,
								javaDocEnd);
						int lengthToRemove = indexOfType - node.getStartPosition();
						int pureLength = node.getLength() - lengthToRemove;
						return (new int[] { indexOfType, pureLength });
					} 
					catch (Exception e) {
						System.out.print(e.getMessage());
					}
				
				}
				if (node instanceof MethodDeclaration) {
					String returnType = ((MethodDeclaration) node)
							.resolveBinding().getReturnType().getName();
					int indexOfType = sourceString.indexOf(returnType,
							javaDocEnd);
					int lengthToRemove = indexOfType - node.getStartPosition();
					int pureLength = node.getLength() - lengthToRemove;
					return (new int[] { indexOfType, pureLength });
				} else {
					return null;
				}
			} else {
				return (new int[] { node.getStartPosition(), node.getLength() });
			}
		} else {
			return (new int[] { node.getStartPosition(), node.getLength() });
		}
	}

	public static void writeSourceLocationArgumentIdentifier(ASTNode node,
			Name name, FactGenerationToolbox generationToolBox) {
		generationToolBox.getFactWriter().writeFact(
				"sl_argT",
				new String[] {
						generationToolBox.getIDResolver().getID(node),
						(new StringBuilder("identifier(")).append(
								quote(name.toString())).append(")").toString(),
						Integer.toString(name.getStartPosition()),
						Integer.toString(name.getLength()) });
	}

	public static void generatePackageFactIfNecessary(IBinding binding,
			FactGenerationToolbox generationToolBox) {
		if (binding == null) {
			return;
		}
		String fullName = binding.getName();
		if (binding.getKind() == 1
				&& generationToolBox.getPackages().get(fullName) == null) {
			String id = generationToolBox.getIDResolver().getID(binding);
			generationToolBox.getFactWriter().writeFact("packageT",
					new String[] { id, quote(fullName) });
			generationToolBox.getPackages().put(fullName, fullName);
		}
	}

	public static String quote(SimpleName name) {
		return quote(name.toString());
	}

	public static void writeSourceLocationArgumentIdentifier(ASTNode node,
			Name name, List list, FactGenerationToolbox generationToolBox) {
		writeSourceLocationArgumentIdentifier(node, name, generationToolBox);
		for (Iterator iter = list.iterator(); iter.hasNext();) {
			Object element = iter.next();
			if (element instanceof Modifier) {
				Modifier modifier = (Modifier) element;
				generationToolBox.getFactWriter().writeFact(
						"sl_argT",
						new String[] {
								generationToolBox.getIDResolver().getID(node),
								(new StringBuilder("modifier(")).append(
										modifier.getKeyword().toString())
										.append(")").toString(),
								Integer.toString(modifier.getStartPosition()),
								Integer.toString(modifier.getLength()) });
			}
		}

	}
//	 public static String getTextForNode(ASTNode node, int offsetdiff, int lendiff)
//	    {
//	        int startPos = node.getStartPosition();
//	        int length = node.getLength();
//	        if(length <= 0)
//	        {
//	            return null;
//	        }
//	        try
//	        {
//	            if(buffer == null)
//	            {
//	                buffer = iCompilationUnit.getBuffer();
//	            }
//	        }
//	        catch(JavaModelException e)
//	        {
//	            JTDebug.report(e);
//	        }
//	        return buffer.getText(startPos + offsetdiff, (length + lendiff) - offsetdiff);
//	    }

}
